(function(layui) {
  'use strict';

  var MODULE_NAME = 'loadingbar';

  layui.define(['jquery', 'element'], function(exports) {
    var $ = layui.jquery;
    var element = layui.element;

    function clamp(n, min, max) {
      if (n < min) {
        return min;
      } else if (n > max) {
        return max;
      } else {
        return n;
      }
    }

    function rgba(color, opacity) {
      if (!/^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.test(color)) { return 'rgba(0,0,0,0)' }

      color = color.slice(1);

      if (color.length === 3) {
        color = color.split('');
        for (var i = 2; i >= 0; i--) {
          color.splice(i, 0, color[i]);
        }
        color = color.join('');
      }

      return 'rgba(' + [
        ~~('0x' + color.slice(0, 2)),
        ~~('0x' + color.slice(2, 4)),
        ~~('0x' + color.slice(4, 6)),
        opacity
      ].join(',') + ')';
    }

    function LoadingBar() {
      this.percent = 0;
      this.state = 0; // 0: pause 1: loading
      this.layID = 'loading-' + (Math.random().toString(36).slice(4) + +new Date());
    }

    var config = LoadingBar.config = {
      failedColor : '#FF5722',
      successColor: '#1E9FFF',
      parent      : 'body',
      height      : '2px',
      zIndex      : 3000
    };

    LoadingBar.prototype.configure = function(options) {
      if ($.type(options) !== 'object') return;

      var key, value;
      for (key in options) {
        value = options[key];
        if (value != null && options['hasOwnProperty'](key)) {
          config[key] = value;
        }
      }
    };

    LoadingBar.prototype.render = function() {
      var $parent = $(config.parent);
      var $progress = $parent.children('#' + this.layID);

      if ($progress.length <= 0) {
        $progress = $('<div id="' + this.layID + '" lay-filter="' + this.layID + '" class="layui-progress"><div class="layui-progress-bar" lay-percent="0%"></div></div>');
        $progress.css({
          backgroundColor: 'transparent',
          height         : config.height,
          position       : 'fixed',
          top            : 0,
          right          : 0,
          left           : 0,
          zIndex         : config.zIndex,
          transition     : 'all 200ms ease'
        });
        $progress.children('.layui-progress-bar').css({
          backgroundColor: config.successColor,
          height         : config.height,
          boxShadow      : '0 0 5px ' + rgba(config.successColor, 0.6)
        });
        $parent.append($progress);
      }

      return $progress;
    };

    LoadingBar.prototype.start = function() {
      if (this.state === 1) {
        this.set(10);
        return;
      }

      var _this = this;
      var $progress = this.render();

      $progress.css('opacity', 1);
      this.state = 1;
      this._timer && clearInterval(this._timer);
      this._timer = setInterval(function() {
        _this.increase();
      }, 200);
      return this;
    };

    LoadingBar.prototype.random = function() {
      var num = 0;

      if (this.percent >= 0 && this.percent < 20) {
        num = Math.random() * 5;
      } else if (this.percent >= 20 && this.percent < 40) {
        num = Math.random() * 3;
      } else if (this.percent >= 40 && this.percent < 80) {
        num = Math.random() * 2;
      } else if (this.percent >= 80 && this.percent < 98) {
        num = Math.random();
      } else if (this.percent >= 98 && this.percent < 100) {
        num = Math.random() / 10;
      }

      return num;
    };

    LoadingBar.prototype.set = function(num) {
      this.percent = num || 0;
      element.progress(this.layID, this.percent + '%');
      return this;
    };

    LoadingBar.prototype.increase = function() {
      if (this.state) {
        this.percent += this.random();
        this.percent = clamp(this.percent, 0, 99.85);
        element.progress(this.layID, this.percent + '%');
      } else {
        this.start();
      }
      return this;
    };

    LoadingBar.prototype.finish = function() {
      this.set(100);
      this.destory();
      return this;
    };

    LoadingBar.prototype.pause = function() {
      clearInterval(this._timer);
      this.state = 0;
      return this;
    };

    LoadingBar.prototype.destory = function() {
      var _this = this;
      var $progress = this.render();
      this.state = 0;
      clearInterval(this._timer);
      setTimeout(function() {
        $progress.css('opacity', 0);
        setTimeout(function() {
          _this.set(0);
          $progress.remove();
        }, 200);
      }, 300);
      return this;
    };

    LoadingBar.prototype.failed = function() {
      $('#' + this.layID).children('.layui-progress-bar').css({
        backgroundColor: config.failedColor,
        boxShadow      : '0 0 5px ' + rgba(config.failedColor, 0.6)
      });
      return this.finish();
    };

    exports(MODULE_NAME, new LoadingBar());
  });
})(layui);
